#ifndef SOBJC_CLASS_H
#define SOBJC_CLASS_H

#include <sobjc-commons/st.h>
#include <sobjc-commons/list.h>
#include <sobjc-commons/type.h>
#include "node.h"

typedef struct objc_class            *objc_class_t;
typedef struct objc_ivar             *objc_ivar_t;
typedef struct objc_method           *objc_method_t;
typedef struct objc_method_sig       *objc_method_sig_t;

OBJC_SIMPLE_DEF_LIST(class_list, objc_class_t)
OBJC_SIMPLE_DEF_LIST(ivar_list, objc_ivar_t)
OBJC_SIMPLE_DEF_LIST(method_list, objc_method_t)

struct objc_class {
  long class_id;
  char *name;
  char *getter;
  BOOL has_impl;
  objc_class_t superclass;
  objc_ivar_list_t ivars;
  char *ivars_repr;
  objc_method_list_t inst_meths;
  objc_method_list_t class_meths;
  objc_class_list_t protocols;
  objc_class_list_t *categories;
  BOOL is_abstract;
  BOOL is_sealed;
  st_table_t inst_dcodes;
  st_table_t class_dcodes;
};

struct objc_ivar {
  objc_node_t node; /* instance-variable-declaration-node */
  char *name;
  int vsbl;
  char *type_name;
  char *ctype;
  objc_type_encoding_t enc;
};

struct objc_method {
  objc_class_t owner;
  objc_node_t node;
  objc_method_sig_t sig;
  int vsbl;
  BOOL is_inst;
  BOOL is_abstract;
  BOOL is_sealed;
  BOOL has_impl;
  char *imp;
};

struct objc_method_sig {
  objc_node_t mtype;
  char *name;
  int nargs;
  int vargs;
  objc_type_encoding_t enc;
};

typedef void (*objc_class_iter_f)(objc_class_t, void *);

extern objc_class_t objc_root_class;

void objc_register_class(objc_class_t);
objc_class_t objc_get_class(char *);
void objc_iter_classes(objc_class_iter_f, void *);

objc_class_t objc_make_class(const char *, objc_class_t);
objc_ivar_t objc_class_get_ivar(objc_class_t, const char *);
objc_method_t objc_class_get_method(objc_class_t, const char *, BOOL);
BOOL objc_class_is_kind_of(objc_class_t, objc_class_t);
int objc_get_dispatch_code(objc_class_t, const char *, BOOL);

objc_method_sig_t objc_register_method_sig(char *, objc_node_t);
objc_method_sig_t objc_get_method_sig(char *);

objc_type_encoding_t objc_make_type_encoding_from_node(objc_node_t);

#endif /* OBJC_CLASS_H */

